/*
 * @Author: wsf
 * @Date: 2019-02-20 16:14:18
 * @LastEditors: wsf
 * @LastEditTime: 2019-08-12 11:33:22
 * @Description: 
 */
import { InputItem, Button, Flex, Modal, ActivityIndicator, ActionSheet, PullToRefresh, DatePickerView } from 'antd-mobile';
import { createForm } from 'rc-form';
import { PureComponent } from "react"
import PropTypes from "prop-types"
import renderCom, { comArr } from "../../utils/renderCom"
import "./MForm.less"
import MAction from "../MAction/MAction"
import { isNull, isArrInStr, calcArr, calcField, filterExpRules, filterExp, filterTemplate, goToPage, isCheckPer, calcPermissionArr, checkPermission, loadScript } from "../../utils/helper"
import MyDatasource from '../MWrapper/MyDataSource';

import pullToRefresh from 'mobile-pull-to-refresh';
import ptrAnimatesMaterial2 from 'mobile-pull-to-refresh/dist/styles/material2/animates';
import 'mobile-pull-to-refresh/dist/styles/material2/style.css';
import Sortable from 'sortablejs';
import { getParmaFromUrl } from '../../utils/request';
let isShowDebug = false;
try {
	isShowDebug = mi_is_dev
} catch (e) {

}
@createForm({
	onFieldsChange: (props, fields, allFields) => {
		let { defaultFormData, dispatch, formDataKey, formData, formRef, config = {} } = props;
		if (isNull(formRef)) {
			return;
		}
		let { setFieldsValue, getFieldDecorator } = formRef;
		let { data_store = {} } = config;
		let { rules = [] } = data_store;
		let newObj = {};
		let changeItems = ",";
		//有些情况下(已知的情况 1、有组件有验证时) 一个form的key的值发生变化时  会执行两次change，当某个key的dirty=false时(正常情况下为true 或者没有) 说明是第二次执行change 此时之后的逻辑就不需要执行
		let isDirty = true, isReset = false;
		for (let item in fields) {
			let { name, value, dirty } = fields[item];
			if (dirty === true) {
				isDirty = false;
			}
			changeItems += name + ",";
			//如果没有value这个属性 说明是重置
			if (!fields[item].hasOwnProperty("value")) {
				newObj[name] = defaultFormData[name];
				isReset = true
			}
			else {
				newObj[name] = value
			}
		}
		if (!isDirty) {
			return;
		}
		formData = {
			...formData,
			...newObj
		};
		//rules 就是需要监听某个key变化后执行的操作的数组
		if (rules instanceof Array && rules.length > 0) {
			rules.map(i => {
				let { on_change, condition, event } = i;
				//判断event配置是否存在 如果不存在就不向下执行
				if (event) {
					//判断on_change中的字段是否在改变的字段中
					if (isArrInStr(on_change, changeItems)) {
						// console.log("isIn");
						let isOk = true;
						//判断condition是否满足条件
						if (!isNull(condition)) {
							isOk = calcField(condition, formData)
						}
						if (isOk) {
							// console.log("isOk");
							let type = event.type;//事件的类型
							if (type == "formula") {//calc计算
								let { formula, key } = event;
								let val;
								try {
									val = eval(filterExp(formula, formData));
									if (isNaN(val)) {
										val = ""
									}
									else {
										val = val.toFixed(2)
									}
								}
								catch (e) {
									console.log(val)
									val = ""
								}
								getFieldDecorator(key);
								setFieldsValue({
									[key]: val
								})
							}
							if (type == "function") {//执行函数
								let { func } = event;
								try {
									eval("(" + func + ")")()
								}
								catch (e) {
									console.log(e);
								}
							}
							if (type == "api") {//请求api 返回结果赋给组件
								let { api, mapping } = event;
								dispatch({
									type: "form/rulesApi",
									payload: {
										apiInfo: api,
										data: formData,
										callback: (result) => {
											let { data, error } = result;
											if (error) {
												data = {}
											}
											if (!isNull(mapping)) {
												if (isReset) {
													data = formData;
													for (let m in mapping) {
														getFieldDecorator(m);
														setFieldsValue({
															[m]: data[m]
														})
													}
												}
												else {
													for (let m in mapping) {
														let k = mapping[m];
														getFieldDecorator(m);
														setFieldsValue({
															[m]: data[k]
														})
													}
												}
											}
										}
									}
								})
							}
							if (type == "data_source") {//请求数据源
								let { id, api, options, source_type } = event;
								dispatch({
									type: "form/getDataSource",
									payload: {
										dataset_key: id,
										source_type,
										options,
										apiInfo: api,
										data: newObj,
										formDataKey
									}
								})
							}
						}
					}
				}
			})
		}
		dispatch({
			type: "form/setFormData",
			payload: {
				key: formDataKey,
				value: newObj
			}
		})
	}
})

export default class MForm extends PureComponent {
	constructor(props) {
		super(props);
		this.modal = "";
		this.state = {
			isReset: false,
			showForm: false,
			height: document.documentElement.clientHeight,
			pullToRefreshOverflow: "unset"
		}
	}
	componentWillMount() {
		console.log(this.props);
		const { defaultFormData, dispatch, formDataKey } = this.props;
		dispatch({
			type: "form/setFormData",
			payload: {
				key: formDataKey,
				value: defaultFormData,
				callback: () => {
					setTimeout(() => {
						this.setState({
							showForm: true
						})
					})
				}
			}
		})
	}

	componentWillReceiveProps(nextProps) {
		let { isShowFooterButton: oldIsShow } = this.props;
		let { isShowFooterButton: newIsShow } = nextProps;
		if (oldIsShow !== newIsShow) {//修改form中，didMount时 isShowFooterButton为false，然后再为true，所以需要监听参数的变化
			this.calcFormHeight(nextProps)
		}
		if (browser.isInApp || true) {//event.after.callback.type=7时触发刷新数据源
			let { isChangeRefreshing: oldIsChangeRefreshing } = this.props;
			let { isChangeRefreshing: newIsChangeRefreshing } = nextProps;

			if (oldIsChangeRefreshing !== newIsChangeRefreshing) {//修改form中，didMount时 isShowFooterButton为false，然后再为true，所以需要监听参数的变化
				this.changeRefreshing()
			}
		}
	}
	changeRefreshing() {
		console.log("刷新")
		let that = this;
		return new Promise(resolve => {
			// this.props.loadConfig({refreshing:true});//下拉刷新时请求config (根据配置确定是否请求)
			setTimeout(() => {
				that.setState({ refreshing: true });
			}, 500);
			setTimeout(() => {
				that.setState({ refreshing: !that.state.refreshing });
				resolve()
			}, 1000);
		})
	}
	calcFormHeight = (props) => {
		//11
		let { isShowFooterButton } = props;
		let height = document.documentElement.clientHeight
		//如果有按钮 或者有footer 就-95
		if (isShowFooterButton || document.getElementById("root").className != "no-footer") {
			// if (browser.isInApp && browser.isInIos) {//不使用app自带tabbar时
			if (browser.isInApp) {
				height = height - 45
			}
			else {//是会用app自带tabbar时
				height = height - 95
			}
		}
		else {
			//否则就-45
			if (browser.isInApp) {
			}
			else {
				height = height - 45
			}
		}
		this.setState({
			height
		})
		try {
			//修复页面显示不完全的bug
			let dom1 = document.querySelector(".am-pull-to-refresh-content-wrapper");
			dom1 = dom1.getElementsByTagName("div")[0];
			dom1.style.minHeight = height * 1 + 26 + "px"//修复页面显示不全的bug
			// dom1.style.minHeight = "1000px"//修复页面显示不全的bug
			// dom1.style.height = "1000px"//修复页面显示不全的bug
		} catch (e) {
			console.log(e)
		}
	}

	componentDidMount() {
		let that = this;
		setTimeout(() => {
			try {
				pullToRefresh({
					container: document.querySelector('.mi_container'),
					animates: ptrAnimatesMaterial2,
					refresh() {
						return new Promise(resolve => {
							// this.props.loadConfig({refreshing:true});//下拉刷新时请求config (根据配置确定是否请求)
							setTimeout(() => {
								that.setState({ refreshing: true });
							}, 500);
							setTimeout(() => {
								that.setState({ refreshing: !that.state.refreshing });
								resolve()
							}, 1000);
						})
					}
				})
			} catch (e) {

			}
		})
		setTimeout(() => {
			this.setState({
				pullToRefreshOverflow: "auto"// 初始是 unset 后改成 auto  解决mi-select-display和 mi-select-more-display 白屏bug
			})
		}, 10)
		setTimeout(() => {
			this.calcFormHeight(this.props);
		}, 300)
		// setTimeout(() => {//可以拖动组件
		// var el = document.getElementsByClassName('mform')[0];
		// var sortable = Sortable.create(el,{
		// 	draggable: ".mform>.page-item",
		// 	// handle: ".sort_box_btn",
		// 	onEnd:function (evt) {
		// 		let children=evt.to.children;
		// 		// //必须是1个才能排序
		// 		 if(children.length>1){
		// 				let newData=[];
		// 				let _k=0;
		// 				for(let dom of children){
		// 						let old_key=dom.getAttribute("sort-key");
		// 				}
		// 		}
		// 	}
		// })
		// }, 1000);
	}

	handleSubmit = (callback) => {
		let { validateFields } = this.props.form;
		validateFields((error, value) => {
			if (!error) {
				callback && callback()
			}
		})
	};

	resetFunc = () => {
		let { resetFields } = this.props.form;
		resetFields();
		this.setState({
			isReset: true
		});
		setTimeout(() => {
			this.setState({
				isReset: false
			})
		})
	};

	footerButtonClick = (item) => {
		let { action_type, confirm_msg = "确定进行此操作？", api = {} } = item;
		let { formData, dispatch } = this.props;
		if (action_type === 0 || action_type === "0") {
			this.modal = Modal.alert("温馨提示", confirm_msg, [
				{ text: "取消", onPress: () => { } },
				{
					text: "确定", onPress: () => {
						dispatch({
							type: "form/query",
							payload: {
								apiInfo: api,
								data: formData
							}
						})
					}
				}
			])
		}
		else {
			let { url } = api;
			goToPage({
				dispatch, config: {
					url: filterTemplate(url, formData)
				}
			})
		}
	};

	render() {
		let { isReset, showForm, pullToRefreshOverflow } = this.state;
		if (!showForm) {
			return (
				<div className="normal">
					<ActivityIndicator toast text="正在加载" animating={true} />
				</div>
			)
		}
		let isTransparent = false;
		try {
			isTransparent = mi_is_transparent
		} catch (e) {

		}
		const { getFieldDecorator, getFieldValue, setFieldsValue, validateFields, resetFields } = this.props.form;
		let { config, dispatch, fd, formDataKey, formData, defaultFormData, isShowFooterButton, footerBtn, isModal, isChangeRefreshing } = this.props;
		let { refreshing } = this.state;
		let { widgets, data_store, options, datasets } = config;
		let { content } = widgets;
		let el = [];
		let dataSets = [];
		let dataSourceObj = {
			formDataKey,
			getFieldValue,
			setFieldsValue,
			isReset,
			refreshing
		};
		if (datasets) {
			for (let i in datasets) {
				let item = datasets[i];
				dataSets.push(
					<MyDatasource key={i} {...item} {...dataSourceObj} id={i} didFormData={formData} />
				)
			}
		}
		let hasListView = false;//有listview和mi-datepicker-scroll组件 整体页面不需要下来刷新
		let usePullToRefresh = true;
		for (let i in content) {
			let item = content[i];
			let key = i;
			let visible = item.visible;
			let newItem = {};
			let _obj = {};
			let { permission_ctrl: _ctrl, permission_code: _code } = item;
			if (isCheckPer(_ctrl, _code) && calcPermissionArr.indexOf(_ctrl) != -1) {
				let per = checkPermission(_code);
				if (item[_ctrl] === undefined) {
					item[_ctrl] = per;
				}
				else {
					_obj[_ctrl] = per
				}
			}
			for (let i in item) {
				let val = item[i];
				if (calcArr.indexOf(i) != -1) {
					let isTrue = calcField(val, formData);
					if (calcPermissionArr.indexOf(i) !== -1) {
						isTrue = isTrue && (_obj[i] !== false);
					}
					newItem[i] = isTrue;
				}
			}
			if (newItem.visible !== "0" && newItem.visible !== 0 && newItem.visible !== false) {
				let comType = item.component_type;
				if (comType === "mi-listview" || comType == "mi-datasendbox" || comType == "mi-datepicker-scroll" || comType === "mi-track-map") {
					hasListView = true;
				}
				let hasMDrawerArr = ["mi-senior-search", "mi-select-contacts", "mi-select-more", "mi-select-more-other", "mi-select-other"];//这些组件中使用了MDrawer组件 PullToRefresh 包含这些组件时，手机端滚动会有bug 所以使用antd中的下拉刷新 
				if (usePullToRefresh) {
					if (hasMDrawerArr.indexOf(comType) != -1) {
						usePullToRefresh = false;
					}
				}

				if (comArr[comType]) {
					let className = "page-item";
					if (item.new_group == 1) {
						className += " new_group"
					}
					let props = {
						isShowFooterButton,
						config,
						isChangeRefreshing,
						refreshing,
						model: "form",
						...item,
						...newItem,
						...options,
						options,
						formData,
						defaultFormData,
						getFieldDecorator,
						getFieldValue,
						setFieldsValue,
						validateFields,
						resetFields,
						isReset,
						dispatch,
						location: this.props.location,
						fd,
						formDataKey,
						setFormData: (value) => {
							dispatch({
								type: "form/setFormData",
								payload: {
									key: formDataKey,
									value
								}
							})
						},
						com_key: i
					}
					el.push(<div key={key} className={className} sort-key={key}>
						{renderCom(props)}
					</div>)
				}
			}
		}

		let { buttons_max = 4 } = options || {};
		let footerButtons = [];
		let footerButtonsMore = [];
		if (isShowFooterButton) {
			usePullToRefresh = false;//底部有按钮时，要使用antd的下拉刷新
			footerBtn.map((item, key) => {
				if (footerBtn.length > buttons_max && key >= buttons_max - 1) {
					footerButtonsMore.push(item);
				}
				else {
					let { disabled, text, event_key, bgcolor, text_color, weight = 1, radius = 5 } = item;
					let flexStyle = {
						flex: weight,
						WebkitBoxFlex: weight,
						WebkitFlex: weight,
					};
					let btnStyle = {
						backgroundColor: bgcolor,
						color: text_color,
						borderRadius: radius + "px"
					};
					footerButtons.push(
						<Flex.Item style={flexStyle} key={key}>
							<Button
								disabled={disabled}
								style={btnStyle}
								onClick={() => {
									MAction({ ...this.props, validateFields, resetFields, getFieldValue, setFieldsValue, resetFunc: this.resetFunc.bind(this) }, event_key)
								}}>{text}</Button>
						</Flex.Item>
					)
				}
			})
			if (footerButtonsMore.length > 0) {
				let options = [];
				footerButtonsMore.map(item => {
					options.push(item.text);
				})
				footerButtons.push(
					<Flex.Item key={-1}>
						<Button icon="ellipsis" onClick={() => {
							ActionSheet.showActionSheetWithOptions({
								options,
								message: "选项"
							}, (index) => {
								if (index != -1) {
									MAction({ ...this.props, validateFields, resetFields, setFieldsValue, resetFunc: this.resetFunc.bind(this) }, footerButtonsMore[index].event_key);
								}
							})
						}}>更多</Button>
					</Flex.Item>
				)
			}
		}
		let formStyle = {
			background: "#f7f7f7"
		};
		if (!hasListView && (localStorage[MI_APP_CODE + "noFooter"] === "false")) {
			formStyle = {
				paddingBottom: "50px"
			}
		}
		//右上角显示戳
		/*
				el.push(
					<img style={{position:"absolute",top:"50px",right:"10px",width:"120px",height:"120px"}} src="image/handled.png" alt="" />
				)
		*/

		if (isModal) {
			//如果是弹窗打开的form 在移动端会因为fixed套fixed而产生footerButton fixed失效的bug
			//所以这种情况下使用data-flex布局
			formStyle = {
				...formStyle,
				paddingBottom: 0,
				height: "100%"
			};

			return (
				<div className="mform" style={formStyle} data-flex="dir:top box:last">
					<div style={{ overflow: "auto", WebkitOverflowScrolling: " touch" }}>
						{dataSets}
						{el}
					</div>
					{
						isShowFooterButton && <Flex justify="center" className="footerButtons" style={{ position: "unset" }}>
							{footerButtons}
						</Flex>
					}
				</div>
			)
		}
		if (hasListView) {
			if (localStorage[MI_APP_CODE + "noFooter"] === "false") {
				formStyle = {
					paddingBottom: "50px"
				}
			}
			return (
				<div className="mform" style={{ ...formStyle, WebkitOverflowScrolling: "touch" }}>
					{/* <Button
						onClick={() => {
							dispatch({
								type: "global/isChangeRefreshing",
								payload: {
									key: formDataKey
								}
							})
						}}
					>111</Button> */}
					<div>
						{dataSets}
						{el}
					</div>
					{
						isShowDebug && <pre><code>{JSON.stringify(formData, null, 2)}</code></pre>
					}
					{
						isShowFooterButton && <Flex justify="center" className="footerButtons" id="footerButtons">
							{footerButtons}
						</Flex>
					}
				</div>
			)
		}
		else {
			if (usePullToRefresh) {//如果不是透明  设成false，MDrawer组件中有滚动时，页面有bug，暂时不适用这个组件
				// if(true){
				//  如果页面中包含轮播图组件时使用这个，界面页面加载不全的bug
				return (
					<div className="mi_container pull-to-refresh-material2" id="test">
						<div className="pull-to-refresh-material2__control">
							<svg className="pull-to-refresh-material2__icon" fill="#4285f4" width="24" height="24" viewBox="0 0 24 24">
								<path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
								<path d="M0 0h24v24H0z" fill="none" />
							</svg>
							<svg className="pull-to-refresh-material2__spinner" width="24" height="24" viewBox="25 25 50 50">
								<circle className="pull-to-refresh-material2__path" cx="50" cy="50" r="20" fill="none" stroke="#4285f4" strokeWidth="4" strokeMiterlimit="10" />
							</svg>
						</div>
						<div className="mform" style={{ ...formStyle, WebkitOverflowScrolling: "touch" }}>
							{/* <Button
								onClick={() => {
									dispatch({
										type: "global/isChangeRefreshing",
										payload: {
											key: formDataKey
										}
									})
								}}
							>111</Button> */}
							{dataSets}
							{el}
							{
								isShowDebug && <pre><code>{JSON.stringify(formData, null, 2)}</code></pre>
							}
							{
								isShowFooterButton ? <Flex justify="center" className="footerButtons" id="footerButtons">
									{footerButtons}
								</Flex> : <div id="footerButtons"></div>
							}
						</div>

					</div>
				)
			}
			return (
				<div className="mform" style={{ ...formStyle, WebkitOverflowScrolling: "touch" }}>
					
					{/* <Button
						onClick={() => {
							dispatch({
								type: "global/isChangeRefreshing",
								payload: {
									key: formDataKey
								}
							})
						}}
					>111</Button> */}
					<PullToRefresh
						distanceToRefresh={50}
						damping={80}
						ref={el => this.ptr = el}
						style={{
							height: this.state.height + "px",
							overflow: pullToRefreshOverflow,
						}}
						indicator={{
							deactivate:
								<div className="pull-to-refresh-material2__control" style={{ top: "-20px", display: 'flex', transform: "translate3d(-50%, 0px, 0px) rotate(0deg)", transition: "all 0.8s ease" }} data-flex>
									<svg className="pull-to-refresh-material2__icon" fill="#4285f4" width="24" height="24" viewBox="0 0 24 24">
										<path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
										<path d="M0 0h24v24H0z" fill="none" />
									</svg>
								</div>,
							activate:
								<div className="pull-to-refresh-material2__control" style={{ top: "-20px", display: 'flex', transform: "translate3d(-50%, 0px, 0px) rotate(360deg)", transition: "all 0.8s ease" }} data-flex>
									<svg className="pull-to-refresh-material2__icon" fill="#4285f4" width="24" height="24" viewBox="0 0 24 24">
										<path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z" />
										<path d="M0 0h24v24H0z" fill="none" />
									</svg>
								</div>,
							release:
								<div className="pull-to-refresh-material2__control" style={{ top: "-20px", display: 'flex' }} data-flex>
									<svg className="pull-to-refresh-material2__spinner" width="24" height="24" viewBox="25 25 50 50"><circle class="pull-to-refresh-material2__path" cx="50" cy="50" r="20" fill="none" stroke="#4285f4" strokeWidth="4" strokeMiterlimit="10"></circle></svg>
								</div>
							,
							finish: " "
						}}
						direction={'down'}
						refreshing={this.state.refreshing}
						onRefresh={() => {
							// this.props.loadConfig({refreshing:true});//下拉刷新时请求config (根据配置确定是否请求)
							setTimeout(() => {
								this.setState({ refreshing: true });
							}, 100);
							setTimeout(() => {
								this.setState({ refreshing: false });
							}, 1000);
						}}
					>
						{dataSets}
						{el}
					</PullToRefresh>
					{
						isShowDebug && <pre><code>{JSON.stringify(formData, null, 2)}</code></pre>
					}
					{
						isShowFooterButton ? <Flex justify="center" className="footerButtons" id="footerButtons">
							{footerButtons}
						</Flex> : <div id="footerButtons"></div>
					}
				</div >
			)
		}

	}
	componentWillUnmount() {
		this.modal && this.modal.close()
	}
}
